home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
utils
/
sort.arc
/
sortcomp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-30
|
22KB
|
719 lines
/******************************************************************************
* *
* sortcomp.c version 1.0 of 1 Januari 1989 (C) L.J.M. de Wit 1989 *
* *
* This software may be used and distributed freely if not used commercially *
* and the originator (me) is mentioned in the source (just leave this 9 line *
* header intact). *
* *
******************************************************************************
*
* sortcomp.c: comparision functions
*
* These functions contain the numeric comparision functions c_n and its
* reverse, c_nr. The other 48 comparision functions are formed by combining
* the following properties (take note of the Capitals):
* a) either Dictionary, Ignore non-printables or Any other (3)
* b) ignore leading Blanks, versus not ignoring them (2)
* c) Fold upper case to lower, versus not folding (2)
* d) Reverse the result of the comparision, versus not reversing (2)
* e) Unbounded (bounded only by '\0'), versus upper limit bound (2)
*
* Since comparing is done a lot it is important for the compare functions
* to be fast. As for using the 48 functions as it stands the following
* arguments are used:
* One could have combined functions and used flags to discern between options.
* This would however involve passing more parameters to the function (the
* flags) and would require (perhaps a lot of) unwanted testing inside the
* function.
* Several functions call one of the other functions. This has been done in
* such a way that duplication of code is mostly prevented, but still this call
* is limited to only one (both in number and in level).
* The numerical compare could have been done by a simple atoi(), but the
* c_n function does the comparision inline, and stops comparing when the
* bigger one has been found (while atoi needs to do calculation ala
* 10 * num + digit, and will use all digits).
*/
#include <stdio.h>
#include <ctype.h>
#include "sortmain.h"
#include "sortcomp.h"
#define SKIPSPACE(bs,bt) while (wspace(*(bs))) (bs)++; while (wspace(*(bt))) (bt)++
#define NCHARS 256
#define NORM 0x1
#define DICT 0x2
#define isnorm(c) (stype[(c)]&NORM)
#define isdict(c) (stype[(c)]&DICT)
#undef isdigit
#define isdigit(c) ((c) >= '0' && (c) <= '9')
static char fold[NCHARS]; /* For lcase conversion */
static char stype[NCHARS]; /* For table lookup */
void initlookup() /* Initialize lookup tables */
{
register int i;
for (i = 0; i < NCHARS; i++) {
fold[i] = isupper(i) ? tolower(i) : i; /* Init lcase convert array */
stype[i] = 0; /* Not really needed ... */
if (i >= 040 && i <= 0176) { /* Ascii non-control */
stype[i] |= NORM;
}
if (wspace(i) || isalnum(i)) { /* Whitespace & alphanum */
stype[i] |= DICT;
}
}
}
int c_nr(bs,bt,es,et) /* Reversed Numeric */
char *bs, *bt;
char *es, *et;
{
return c_n(bt,bs,et,es);
}
int c_n(bs,bt,es,et) /* Numeric compare */
register char *bs, *bt;
char *es, *et;
{
register int rev, mini;
SKIPSPACE(bs,bt);
if (*bs == '-') {
if (*bt == '-') { /* Two negatives: reverse */
rev = -1;
bs++;
bt++;
} else { /* bt will be the larger one*/
return -1;
}
} else {
if (*bt == '-') { /* bs will be the larger one*/
return 1;
} else {
rev = 1; /* Both positive */
}
}
while (*bs == *bt && isdigit(*bt)) { /* Compare & skip eq. digits*/
bs++; bt++;
}
if (!isdigit(*bs)) {
if (!isdigit(*bt)) {
if (*bs == '.' && *bt == '.') { /* Decimal point */
while (*++bs == *++bt && isdigit(*bt)) ;
while (*bs == '0') bs++; /* Skip possibly trailing */
while (*bt == '0') bt++; /* zeroes */
if (!isdigit(*bs)) {
if (!isdigit(*bt)) {
return 0; /* Tails also equal */
}
return -rev; /* bt has more digits */
}
if (!isdigit(*bt)) {
return rev; /* bs has more digits */
}
return (rev == 1) /* Current digit decides */
? (*bs - *bt) : (*bt - *bs);
} else {
return 0; /* Equal numeric strings */
}
}
return -rev; /* bt has more digits */
}
if (!isdigit(*bt)) {
return rev; /* bs has more digits */
}
mini = (rev == 1) /* Current digit decides: */
? (*bs - *bt) : (*bt - *bs); /* Difference into mini */
do {
bs++;
bt++;
} while (isdigit(*bs) && isdigit(*bt)); /* Skip any more digits */
if (!isdigit(*bs)) {
if (!isdigit(*bt)) { /* Strings equally long: */
return mini; /* then mini decides */
}
return -rev; /* bt has more digits */
}
return rev; /* bs has more digits */
}
int c_df(bs,bt,es,et) /* Dictionary/Fold */
register char *bs, *bt; /* Strings to compare */
register char *es, *et;
{
--bs; --bt; --es; --et;
for ( ; bs < es && bt < et; ) {
if (fold[*++bs] != fold[*++bt]) { /* Increment & compare */
if (isdict(*bs)) {
if (isdict(*bt)) {
return fold[*bs] - fold[*bt];
} else {
--bs; /* Effectively skip *bt */
}
} else if (isdict(*bt)) {
--bt; /* Effectively skip *bs */
} /* (else: skip both) */
}
}
for ( ; bs < es; ) { /* Skip any more */
if (isdict(*++bs)) { /* non-dict chars in bs */
--bs;
break;
}
}
for ( ; bt < et; ) { /* Skip any more */
if (isdict(*++bt)) { /* non-dict chars in bt */
--bt;
break;
}
}
return (et - bt) - (es - bs);
}
int c_d(bs,bt,es,et) /* Dictionary order */
register char *bs, *bt;
register char *es, *et;
{
--bs; --bt; --es; --et;
for ( ; bs < es && bt < et; ) {
if (*++bs != *++bt) { /* Increment & compare */
if (isdict(*bs)) {
if (isdict(*bt)) {
return fold[*bs] - fold[*bt];
} else {
--bs; /* Effectively skip *bt */
}
} else if (isdict(*bt)) {
--bt; /* Effectively skip *bs */
} /* (else: skip both) */
}
}
for ( ; bs < es; ) { /* Skip any more */
if (isdict(*++bs)) { /* non-dict chars in bs */